/***************************************************************************
 *   Copyleft 2006-2007 by												   *
 *	 Iwanicki Krzysztof													   *
 *   <gamma.mini.pw.edu.pl/~iwanickik>									   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 ***************************************************************************/
#include "./Scene3D.h"

/**************************************************************
* Constructors                                                *
***************************************************************/
Scene3D::Scene3D() {
	mWorldMatrix = Matrix4D::Translation(Point4D(0.0f, 0.0f, 0.0f));
	mCursor = cNull;
}

Scene3D::~Scene3D() {
	for (ObjectsListIt it = mObjects.begin(); it != mObjects.end(); it++) {
		if (*it) {
			delete (*it);
		}
	}
	mObjects.clear();
	if (mCursor) {
		delete mCursor;
	}
}
    
/**************************************************************
* Operators                                                   *
***************************************************************/


/**************************************************************
* Other helpful functions                                     *
***************************************************************/
cVoid Scene3D::AddCursor(Cursor3D* cursor) {
	if (cursor) {
		if (mCursor) {
			delete mCursor;
		}
		mCursor = cursor;
	}
}

Cursor3D* Scene3D::GetCursor() {
	if (mCursor) {
		return mCursor;
	} else {
		return cNull;
	}
}

cVoid Scene3D::AddObject(Object3D* object) {
	if (object) {
		mObjects.push_back(object);
	}
}

cVoid Scene3D::RemoveObject(Object3D* object, cBool bDelete) {
	if (object) {
		mObjects.remove(object);
		if (bDelete) {
			delete object;
		}
	}
}

cVoid Scene3D::RemoveObject(Object3D* object) {
	if (object) {
		mObjects.remove(object);
		delete object;
	}
}

Object3D* Scene3D::ReplaceObject(Object3D* oldObject, Object3D* newObject) {
	for (ObjectsListIt it = mObjects.begin(); it != mObjects.end(); it++) {
		if (*it == oldObject)	{
			*it = newObject;
			return oldObject;
		}
	}

	return cNull;
}

Object3D* Scene3D::GetObject(cInt iIndex) {
	cInt i = 0;
	for (ObjectsListIt it = mObjects.begin(); it != mObjects.end(); it++, i++) {
		if (i == iIndex) {
			return *it;
		}
	}

	return cNull;
}

Object3D* Scene3D::GetObjectByID(cInt iID) {
	for (ObjectsListIt it = mObjects.begin(); it != mObjects.end(); it++) {
		if ((*it)->GetID() == iID) {
			return *it;
		}
	}

	return cNull;
}

ObjectsList& Scene3D::GetObjects() {
	return mObjects;
}

cInt Scene3D::GetNrOfObjects() {
	return (cInt) mObjects.size() - 3;
}

Matrix4D& Scene3D::GetWorldMatrix() {
	return mWorldMatrix;
}

cVoid Scene3D::SetWorldMatrix(Matrix4D& matrix) {
	mWorldMatrix = matrix;
}

cVoid Scene3D::Reset() {
	mWorldMatrix = Matrix4D::Identity();
}


cVoid Scene3D::Transform(Matrix4D& matrix) {
	mWorldMatrix = matrix * mWorldMatrix;
}

cVoid Scene3D::Render(Renderer& renderer, Matrix4D& projectionMatrix, ProjectionPlane& plane) {
	Matrix4D matrix = projectionMatrix * mWorldMatrix;

	for (ObjectsListIt it = mObjects.begin(); it != mObjects.end(); it++) {
		if (*it) {
			if ((*it)->GetName() != "Ellipsoid") {
				(*it)->Render(renderer, matrix, plane);
			} else {
				(*it)->Render(renderer, Matrix4D::Translation(Point4D(0.0f, 0.0f, 1000.0f)), plane);
			}
		}
	}
}

cVoid Scene3D::Render(Renderer& renderer, Matrix4D& projectionMatrix, ProjectionPlane& plane, cWinColor color) {
	Matrix4D matrix = projectionMatrix * mWorldMatrix;

	for (ObjectsListIt it = mObjects.begin(); it != mObjects.end(); it++) {
		if (*it) {
			if ((*it)->GetName() != "Ellipsoid") {
				(*it)->Render(renderer, matrix, plane, color);
			}
		}
	}
}

cVoid Scene3D::RenderCursor(Renderer& renderer, Matrix4D& projectionMatrix, ProjectionPlane& plane) {
	if (mCursor) {
		mCursor->Render(renderer, projectionMatrix * mWorldMatrix, plane);
		mCursor->DisplayInfo(renderer);
	}
}

cVoid Scene3D::RenderCursor(Renderer& renderer, Matrix4D& projectionMatrix, ProjectionPlane& plane, cWinColor color) {
	if (mCursor) {
		((Object3D*) mCursor)->Render(renderer, projectionMatrix * mWorldMatrix, plane, color);
		mCursor->DisplayInfo(renderer);
	}
}